package controllers

import (
	"encoding/base64"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

type XfyunBaseController struct {
	BaseController
}

// 生成form-data
func CreateFormdata(md map[string]string) (str string) {
	str = ""
	for key, val := range md {
		str += ps("%s=%s&", key, val)
	}

	if len(str) > 0 {
		str = str[0 : len(str)-1]
	}
	return
}

/* auf(0/1),aue(raw/lame),voice_name(发音人:xiaoyan),speed,volume,pitch,
 * engine_type(aisound-普通效果,intp65-中文,intp65_en-英文,mtts-小语种,需配合小语种发音人使用,x-优化效果,默认为intp65),text
 *
 */
func (this *XfyunBaseController) AudioGeneRate() {
	map_param := make(map[string]string)
	auf, _ := this.GetInt32("auf", 0)
	if auf == 0 {
		map_param["auf"] = "audio/L16;rate=8000"
	} else {
		map_param["auf"] = "audio/L16;rate=16000"
	}
	map_param["aue"] = this.GetString("aue")
	map_param["voice_name"] = this.GetString("voice_name")
	map_param["speed"] = this.GetString("speed")
	map_param["volume"] = this.GetString("volume")
	map_param["pitch"] = this.GetString("pitch")
	map_param["engine_type"] = this.GetString("engine_type")
	map_param["text_type"] = "text"

	json_bytes, err := json.Marshal(map_param)
	if err != nil {
		log("构造json失败:%s", err.Error())
		return
	}
	//log("json:%s", json_bytes)
	json_base64 := base64.StdEncoding.EncodeToString(json_bytes)

	// 发送请求
	timeout := time.Duration(8 * time.Second)
	client := &http.Client{
		Timeout: timeout,
	}

	map_req := make(map[string]string)
	map_req["text"] = url.QueryEscape(this.GetString("text"))
	strval := CreateFormdata(map_req)
	url := "http://api.xfyun.cn/v1/service/v1/tts"
	req, err := http.NewRequest("POST", url, strings.NewReader(strval))
	if err != nil {
		this.Rec = &Recv{5, "合成失败,创建请求失败", nil}
		return
	}

	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
	req.Header.Set("X-Param", json_base64)
	apiId := "5bc6a98f"
	req.Header.Set("X-Appid", apiId)
	curTime := ps("%v", TimeNow)
	req.Header.Set("X-CurTime", curTime)
	apiKey := "8f8303780b9ed7232f7409f449352a80"
	checkSum := StrToMD5(apiKey + curTime + json_base64)
	req.Header.Set("X-CheckSum", checkSum)
	//req.Header.Set("X-Real-Ip", "124.78.72.176")
	resp, err := client.Do(req)
	if err != nil {
		log("发送请求失败:%s", err.Error())
		return
	}
	defer resp.Body.Close()

	recv_url := ""
	ret := resp.StatusCode
	if resp.StatusCode == 200 {
		log("header:%v", resp.Header)
		ct, ok := resp.Header["Content-Type"]
		if ok {
			log("Content-Type:%v", ct)
			if ct[0] == "text/plain" {
				recv, err := ioutil.ReadAll(resp.Body)
				if err == nil {
					type RecvData struct {
						Code string `json:"code"`
						Data string `json:"data"`
						Desc string `json:"desc"`
						Sid  string `json:"sid"`
					}
					var data RecvData
					err = json.Unmarshal(recv, &data)
					if err != nil {
						log("解析json异常:[%s]", err.Error())
						this.Rec = &Recv{5, "合成失败,解析json异常", nil}
					} else {
						this.Rec = &Recv{5, "合成失败", &data}
					}
				} else {
					log("read buf fail:%s", err.Error())
					this.Rec = &Recv{5, "合成失败,读取数据错误", nil}
				}
				return
			} else {
				filename := ""
				if map_param["aue"] == "raw" {
					filename = ps("%d_%s.wav", TimeNow, GetRandomS(6))
				} else {
					filename = ps("%d_%s.mp3", TimeNow, GetRandomS(6))
				}
				filepath := ps("%s/%s", conf("xfyunpath"), filename)
				log("filepath:%s", filepath)
				file, err := os.Create(filepath)
				if err != nil {
					log("创建文件失败:%s", err.Error())
					this.Rec = &Recv{3, "合成失败,创建文件失败", nil}
					return
				}
				defer file.Close()
				recv, err := ioutil.ReadAll(resp.Body)
				if err == nil {
					num, err := file.Write(recv)
					if err != nil {
						log("写入文件失败:%s", err.Error())
						this.Rec = &Recv{5, "合成失败,写入文件失败", nil}
						return
					}
					log("写入字节数:%d", num)
				} else {
					log("read buf fail:%s", err.Error())
					this.Rec = &Recv{5, "合成失败,读取数据错误", nil}
					return
				}
				recv_url = ps("http://%s:%s%s/%s", conf("domain"), conf("httpport"), conf("xfyundown"), filename)
			}
		}

	} else {
		err = errors.New(ps("Response StatusCode err:%v", ret))
	}

	this.Rec = &Recv{3, "合成成功", recv_url}
}
